#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Name:       Python M-JPEG Over HTTP Client Program
Version:    0.1
Purpose:    This program connects to an MJPEG stream and saves retrived images.
Author:     Sergey Lalov
Date:       2011-03-30
License:    GPL
Target:     Cross Platform
Require:    Python 2.6+
"""

from CommunicationControler import CommunicationControler
import time, os, re


debug = 0
class VideoDownloader:
    
    def __init__(self ,config, cameraName ,savePath):
        config['callback'] = self.processImage
        legalName = re.compile('^[a-zA-Z0-9_\- ]+$')
        if (legalName.match(cameraName)== None):
            raise NameError('Camera Name "%s" is Ilegal!'%cameraName)
        self.__communicationControler = CommunicationControler()
        self.__times = list()
        self.frameSpeed = 0
        self.backSeconds = 3
        self.lastImg = None
        self.imgC = 0
        self.__startTime = None
        self.__savePath = savePath
        self.__cameraName = cameraName
        self.__communicationControler.addReader(cameraName, config)
        self.__watch = False

    def __del__(self):
        self.__communicationControler.removeReader(self.__cameraName)
        
    def getFrameSpeed(self):
        currT = time.time()
        currC = 0
        firstT = None
        for x in self.__times:
            if currT - x < self.backSeconds:
               currC = currC + 1      
            if firstT == None:
                firstT = x

        self.__times = [x for x in self.__times if currT - x < self.backSeconds]
        
        if firstT <> None and currT <> firstT:
            self.frameSpeed = currC / (currT - firstT)
        else:
             self.frameSpeed = 0
             self.imgC = 0
        return self.frameSpeed

    def processImage(self,img):
        'This function is invoked by the MJPEG Client protocol'
        # Process image
        # Just save it as a file in this example
        if (self.__startTime == None and not(self.__watch)):
            raise NameError('Someone had started the handler without calling startRecord')
        if (debug):
            print 'Got Image'
        currT = time.time()
        self.__times.append(currT)
        self.getFrameSpeed()
        self.imgC = self.imgC + 1
        self.lastImg = img
        vidFolderPath = os.path.join(self.__savePath, self.__cameraName ,'%s_%s'%(self.__cameraName ,time.strftime('%d-%m-%Y_%H-%M-%S' , time.localtime(self.__startTime))))
        if (self.__startTime != None):
            if (not(os.path.exists(vidFolderPath))):
                os.makedirs(vidFolderPath)
            fullPath = os.path.join(vidFolderPath, 'frame%d.jpg'%self.imgC)
            f = open(fullPath, 'wb')
            f.write(img)
            f.close()
        
    def startRecord(self):
        # Make a connection
        if (self.__startTime == None):
            self.__startTime = time.time()
            self.imgC = 0
            self.__watch = True
        self.__communicationControler.activateCamera(self.__cameraName)
        
    def stopWatch(self):
        self.__communicationControler.deActivateCamera(self.__cameraName)
        if self.__startTime <> None:
            endTime = time.time()
            vidTime = (endTime - self.__startTime)
            stTime =  time.strftime('%d-%m-%Y_%H-%M-%S' , time.localtime(self.__startTime))
            edTime =  time.strftime('%d-%m-%Y_%H-%M-%S' , time.localtime(endTime))
            vidFolderPath = os.path.join(self.__savePath, self.__cameraName, '%s_%s'%(self.__cameraName ,stTime))
            if (vidTime > 0 and self.imgC > 0):
                currFps = self.imgC / vidTime
                fullVidPath = os.path.join(vidFolderPath, 'video_info.txt')
                f = open(fullVidPath, 'w')
                f.write('StartTime: %s\n'%stTime)
                f.write('EndTime: %s\n'%edTime)
                f.write('FrameCount: %d\n'%self.imgC)
                f.write('FPS: %s'%currFps)
                f.close()
        self.lastImg = None
        self.__startTime = None
        self.__watch = False

    def stopRecord(self):
        if not(self.__watch):
            self.__communicationControler.deActivateCamera(self.__cameraName)
        startTime = self.__startTime
        self.lastImg = None
        self.__startTime = None
        if startTime <> None:
            endTime = time.time()
            vidTime = (endTime - startTime)
            stTime =  time.strftime('%d-%m-%Y_%H-%M-%S' , time.localtime(startTime))
            edTime =  time.strftime('%d-%m-%Y_%H-%M-%S' , time.localtime(endTime))
            vidFolderPath = os.path.join(self.__savePath, self.__cameraName, '%s_%s'%(self.__cameraName ,stTime))
            if (vidTime > 0 and self.imgC > 0):
                currFps = self.imgC / vidTime
                fullVidPath = os.path.join(vidFolderPath, 'video_info.txt')
                f = open(fullVidPath, 'w')
                f.write('StartTime: %s\n'%stTime)
                f.write('EndTime: %s\n'%edTime)
                f.write('FrameCount: %d\n'%self.imgC)
                f.write('FPS: %s'%currFps)
                f.close()

    def onlyWatch(self):
        self.__watch = True
        self.__communicationControler.activateCamera(self.__cameraName)        

    def watchStatus(self):
        camOn = self.__communicationControler.IsActive(self.__cameraName)
        finalRes = camOn and self.__watch
        return finalRes
    
    def recordStatus(self):
        camOn = self.__communicationControler.IsActive(self.__cameraName)
        return camOn and self.__startTime != None

    def exitAndClean(self):      
        self.__communicationControler.StopAll()
        
